Merge 2.4/2.6 shutdown/suspend control message handling code.
current->used_math = 0;
stts();
}
-
-
-/******************************************************************************
- * Stop/pickle callback handling.
- */
-
-#include <asm/suspend.h>
-
-/* Ignore multiple shutdown requests. */
-static int shutting_down = -1;
-
-static void __do_suspend(void)
-{
- int i,j;
- /* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */
- extern void blkdev_suspend(void);
- extern void blkdev_resume(void);
- extern void netif_suspend(void);
- extern void netif_resume(void);
- extern void time_suspend(void);
- extern void time_resume(void);
-
- suspend_record_t *suspend_record = NULL;
-
- if ( (suspend_record = (suspend_record_t *)__get_free_page(GFP_KERNEL))
- == NULL )
- goto out;
-
- suspend_record->nr_pfns = max_pfn; /* final number of pfns */
-
- __cli();
-
- netif_suspend();
-
- blkdev_suspend();
-
- time_suspend();
-
- ctrl_if_suspend();
-
- irq_suspend();
-
- HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
- clear_fixmap(FIX_SHARED_INFO);
-
- memcpy(&suspend_record->resume_info, &start_info, sizeof(start_info));
-
- HYPERVISOR_suspend(virt_to_machine(suspend_record) >> PAGE_SHIFT);
-
- shutting_down = -1;
-
- memcpy(&start_info, &suspend_record->resume_info, sizeof(start_info));
-
- set_fixmap(FIX_SHARED_INFO, start_info.shared_info);
-
- HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
-
- memset(empty_zero_page, 0, PAGE_SIZE);
-
- for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ )
- {
- pfn_to_mfn_frame_list[j] =
- virt_to_machine(&phys_to_machine_mapping[i]) >> PAGE_SHIFT;
- }
- HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
- virt_to_machine(pfn_to_mfn_frame_list) >> PAGE_SHIFT;
-
-
- irq_resume();
-
- ctrl_if_resume();
-
- time_resume();
-
- blkdev_resume();
-
- netif_resume();
-
- __sti();
-
-
- out:
- if ( suspend_record != NULL )
- free_page((unsigned long)suspend_record);
-}
-
-static int shutdown_process(void *__unused)
-{
- static char *envp[] = { "HOME=/", "TERM=linux",
- "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
- static char *restart_argv[] = { "/sbin/shutdown", "-r", "now", NULL };
- static char *poweroff_argv[] = { "/sbin/halt", "-p", NULL };
-
- extern asmlinkage long sys_reboot(int magic1, int magic2,
- unsigned int cmd, void *arg);
-
- daemonize();
-
- switch ( shutting_down )
- {
- case CMSG_SHUTDOWN_POWEROFF:
- if ( execve("/sbin/halt", poweroff_argv, envp) < 0 )
- {
- sys_reboot(LINUX_REBOOT_MAGIC1,
- LINUX_REBOOT_MAGIC2,
- LINUX_REBOOT_CMD_POWER_OFF,
- NULL);
- }
- break;
-
- case CMSG_SHUTDOWN_REBOOT:
- if ( execve("/sbin/shutdown", restart_argv, envp) < 0 )
- {
- sys_reboot(LINUX_REBOOT_MAGIC1,
- LINUX_REBOOT_MAGIC2,
- LINUX_REBOOT_CMD_RESTART,
- NULL);
- }
- break;
- }
-
- return 0;
-}
-
-static void __shutdown_handler(void *unused)
-{
- int err;
-
- if ( shutting_down != CMSG_SHUTDOWN_SUSPEND )
- {
- err = kernel_thread(shutdown_process, NULL, CLONE_FS | CLONE_FILES);
- if ( err < 0 )
- printk(KERN_ALERT "Error creating shutdown process!\n");
- else
- shutting_down = -1; /* could try again */
- }
- else
- {
- __do_suspend();
- }
-}
-
-static void shutdown_handler(ctrl_msg_t *msg, unsigned long id)
-{
- static struct tq_struct shutdown_tq;
-
- if ( (shutting_down == -1) &&
- ((msg->subtype == CMSG_SHUTDOWN_POWEROFF) ||
- (msg->subtype == CMSG_SHUTDOWN_REBOOT) ||
- (msg->subtype == CMSG_SHUTDOWN_SUSPEND)) )
- {
- shutting_down = msg->subtype;
- shutdown_tq.routine = __shutdown_handler;
- schedule_task(&shutdown_tq);
- }
- else
- {
- printk("Ignore spurious shutdown request\n");
- }
-
- ctrl_if_send_response(msg);
-}
-
-static int __init setup_shutdown_event(void)
-{
- ctrl_if_register_receiver(CMSG_SHUTDOWN, shutdown_handler, 0);
- return 0;
-}
-
-__initcall(setup_shutdown_event);
static long clock_cmos_diff;
-static int time_suspend(struct sys_device *dev, u32 state)
+static int __time_suspend(struct sys_device *dev, u32 state)
{
/*
* Estimate time zone so that set_time can update the clock
return 0;
}
-static int time_resume(struct sys_device *dev)
+static int __time_resume(struct sys_device *dev)
{
unsigned long sec = get_cmos_time() + clock_cmos_diff;
write_seqlock_irq(&xtime_lock);
}
static struct sysdev_class pit_sysclass = {
- .resume = time_resume,
- .suspend = time_suspend,
+ .resume = __time_resume,
+ .suspend = __time_suspend,
set_kset_name("pit"),
};
return ret;
}
+void time_suspend(void)
+{
+}
+
+void time_resume(void)
+{
+ unsigned long flags;
+ write_lock_irqsave(&xtime_lock, flags);
+ /* Get timebases for new environment. */
+ __get_time_values_from_xen();
+ /* Reset our own concept of passage of system time. */
+ processed_system_time = shadow_system_time;
+ /* Accept a warp in UTC (wall-clock) time. */
+ last_seen_tv.tv_sec = 0;
+ /* Make sure we resync UTC time with Xen on next timer interrupt. */
+ last_update_from_xen = 0;
+ write_unlock_irqrestore(&xtime_lock, flags);
+}
+
/*
* /proc/sys/xen: This really belongs in another file. It can stay here for
* now however.
+#define __KERNEL_SYSCALLS__
+static int errno;
+#include <linux/errno.h>
#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/unistd.h>
#include <linux/module.h>
#include <linux/reboot.h>
+#include <asm/irq.h>
+#include <asm/mmu_context.h>
+#include <asm-xen/ctrl_if.h>
#include <asm-xen/hypervisor.h>
+#include <asm-xen/hypervisor-ifs/dom0_ops.h>
+#include <asm-xen/suspend.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
int reboot_thru_bios = 0; /* for dmi_scan.c */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
EXPORT_SYMBOL(machine_power_off);
#endif
+
+
+
+/******************************************************************************
+ * Stop/pickle callback handling.
+ */
+
+#include <asm/suspend.h>
+
+/* Ignore multiple shutdown requests. */
+static int shutting_down = -1;
+
+static void __do_suspend(void)
+{
+ int i,j;
+ /* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */
+ extern void blkdev_suspend(void);
+ extern void blkdev_resume(void);
+ extern void netif_suspend(void);
+ extern void netif_resume(void);
+ extern void time_suspend(void);
+ extern void time_resume(void);
+ extern unsigned long max_pfn;
+ extern unsigned long *pfn_to_mfn_frame_list;
+
+ suspend_record_t *suspend_record = NULL;
+
+ if ( (suspend_record = (suspend_record_t *)__get_free_page(GFP_KERNEL))
+ == NULL )
+ goto out;
+
+ suspend_record->nr_pfns = max_pfn; /* final number of pfns */
+
+ __cli();
+
+ netif_suspend();
+
+ blkdev_suspend();
+
+ time_suspend();
+
+ ctrl_if_suspend();
+
+ irq_suspend();
+
+ HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
+ clear_fixmap(FIX_SHARED_INFO);
+
+ memcpy(&suspend_record->resume_info, &start_info, sizeof(start_info));
+
+ HYPERVISOR_suspend(virt_to_machine(suspend_record) >> PAGE_SHIFT);
+
+ shutting_down = -1;
+
+ memcpy(&start_info, &suspend_record->resume_info, sizeof(start_info));
+
+ set_fixmap(FIX_SHARED_INFO, start_info.shared_info);
+
+ HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
+
+ memset(empty_zero_page, 0, PAGE_SIZE);
+
+ for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ )
+ {
+ pfn_to_mfn_frame_list[j] =
+ virt_to_machine(&phys_to_machine_mapping[i]) >> PAGE_SHIFT;
+ }
+ HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
+ virt_to_machine(pfn_to_mfn_frame_list) >> PAGE_SHIFT;
+
+
+ irq_resume();
+
+ ctrl_if_resume();
+
+ time_resume();
+
+ blkdev_resume();
+
+ netif_resume();
+
+ __sti();
+
+
+ out:
+ if ( suspend_record != NULL )
+ free_page((unsigned long)suspend_record);
+}
+
+static int shutdown_process(void *__unused)
+{
+ static char *envp[] = { "HOME=/", "TERM=linux",
+ "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
+ static char *restart_argv[] = { "/sbin/shutdown", "-r", "now", NULL };
+ static char *poweroff_argv[] = { "/sbin/halt", "-p", NULL };
+
+ extern asmlinkage long sys_reboot(int magic1, int magic2,
+ unsigned int cmd, void *arg);
+
+ daemonize(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ "shutdown"
+#endif
+ );
+
+ switch ( shutting_down )
+ {
+ case CMSG_SHUTDOWN_POWEROFF:
+ if ( execve("/sbin/halt", poweroff_argv, envp) < 0 )
+ {
+ sys_reboot(LINUX_REBOOT_MAGIC1,
+ LINUX_REBOOT_MAGIC2,
+ LINUX_REBOOT_CMD_POWER_OFF,
+ NULL);
+ }
+ break;
+
+ case CMSG_SHUTDOWN_REBOOT:
+ if ( execve("/sbin/shutdown", restart_argv, envp) < 0 )
+ {
+ sys_reboot(LINUX_REBOOT_MAGIC1,
+ LINUX_REBOOT_MAGIC2,
+ LINUX_REBOOT_CMD_RESTART,
+ NULL);
+ }
+ break;
+ }
+
+ shutting_down = -1; /* could try again */
+
+ return 0;
+}
+
+static void __shutdown_handler(void *unused)
+{
+ int err;
+
+ if ( shutting_down != CMSG_SHUTDOWN_SUSPEND )
+ {
+ err = kernel_thread(shutdown_process, NULL, CLONE_FS | CLONE_FILES);
+ if ( err < 0 )
+ printk(KERN_ALERT "Error creating shutdown process!\n");
+ }
+ else
+ {
+ __do_suspend();
+ }
+}
+
+static void shutdown_handler(ctrl_msg_t *msg, unsigned long id)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
+#else
+ static struct tq_struct shutdown_tq;
+#endif
+
+ if ( (shutting_down == -1) &&
+ ((msg->subtype == CMSG_SHUTDOWN_POWEROFF) ||
+ (msg->subtype == CMSG_SHUTDOWN_REBOOT) ||
+ (msg->subtype == CMSG_SHUTDOWN_SUSPEND)) )
+ {
+ shutting_down = msg->subtype;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ schedule_work(&shutdown_work);
+#else
+ shutdown_tq.routine = __shutdown_handler;
+ schedule_task(&shutdown_tq);
+#endif
+ }
+ else
+ {
+ printk("Ignore spurious shutdown request\n");
+ }
+
+ ctrl_if_send_response(msg);
+}
+
+static int __init setup_shutdown_event(void)
+{
+ ctrl_if_register_receiver(CMSG_SHUTDOWN, shutdown_handler, 0);
+ return 0;
+}
+
+__initcall(setup_shutdown_event);
extern void unbind_virq_from_irq(int virq);
extern int bind_evtchn_to_irq(int evtchn);
extern void unbind_evtchn_from_irq(int evtchn);
+
+extern void irq_suspend(void);
+extern void irq_resume(void);
#endif /* __ASSEMBLY__ */
#endif /* _ASM_IRQ_VECTORS_H */